<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
    <title>图片分类工具</title>
    <link href="/css/bootstrap.min.css" rel="stylesheet">
    <style>
        body {
            display: flex;
            flex-direction: column;
            height: 100vh;
            margin: 0;
        }

        body.loading::after {
            content: "正在处理，请稍候...";
            position: fixed;
            top: 0;
            left: 0;
            right: 0;
            bottom: 0;
            background: rgba(255, 255, 255, 0.8); /* 半透明背景 */
            z-index: 1000;
            display: flex;
            align-items: center;
            justify-content: center;
            font-size: 1.2rem;
            color: #333;
        }

        .container-fluid {
            flex: 1;
            min-height: 0;
            display: flex;
            overflow: hidden;
            width: 100%;
            margin: 0;
            padding: 0;
            box-sizing: border-box;
        }

        .sidebar, .main-content {
            padding: 1rem;
            border: 1px solid #ddd;
            flex: 1;
            overflow-y: auto;
            display: flex;
            flex-direction: column;
        }

        .sidebar {
            margin-right: 0.5rem;
        }

        .main-content {
            margin-left: 0.5rem;
        }

        ul {
            list-style-type: none;
            padding-left: 0;
            flex-grow: 1;
        }

        li.folder {
            cursor: pointer;
            font-weight: bold;
        }

        li.file-item {
            display: flex;
            align-items: center;
            margin-bottom: 1rem;
        }

        .file-checkbox {
            margin-right: 0.5rem;
        }

        .header {
            display: flex;
            align-items: center;
            justify-content: space-between;
            padding: 1rem;
            background-color: #f8f9fa;
            border-bottom: 1px solid #ddd;
        }

        .upload-form {
            display: flex;
            gap: 0.5rem;
            align-items: center;
        }

        .upload-form input[type="file"] {
            flex: 1;
        }

        .upload-form button {
            white-space: nowrap;
        }

        .message-box-container {
            padding: 1rem;
            border-top: 1px solid #ddd;
            background-color: #f9f9f9;
            overflow: hidden;
            white-space: pre-wrap;
            word-wrap: break-word;
            height: 150px;
            flex-shrink: 0;
            position: relative;
        }

        #messageBox {
            height: 100%;
            overflow-y: auto;
            position: absolute;
            top: 0;
            left: 0;
            right: 0;
            bottom: 0;
        }

        .path-display {
            margin-bottom: 1rem;
            font-size: 18px;
            color: #555;
        }

        .file-icon, .folder-icon, .thumbnail {
            width: 32px;
            height: 32px;
            margin-right: 0.5rem;
            display: inline-block;
            vertical-align: middle;
        }

        .file-name {
            line-height: 32px;
        }

        .context-menu {
            position: absolute;
            background-color: #fff;
            border: 1px solid #ccc;
            box-shadow: 2px 2px 5px rgba(0, 0, 0, 0.2);
            z-index: 1000;
        }

        .context-menu ul {
            list-style-type: none;
            margin: 0;
            padding: 0;
        }

        .context-menu ul li {
            padding: 8px 12px;
            cursor: pointer;
        }

        .context-menu ul li:hover {
            background-color: #f1f1f1;
        }
    </style>
    <script src="/js/axios.min.js"></script>
</head>
<body>
<div class="header bg-light">
    <form id="uploadForm" enctype="multipart/form-data" class="upload-form">
        <input type="file" id="fileInput" name="files" multiple required class="form-control">
        <button type="button" onclick="uploadFiles()" class="btn btn-primary">上传图片</button>
        <button type="button" onclick="classifyImages()" class="btn btn-success">开始分类</button>
        <button type="button" onclick="bindImages()" class="btn btn-warning">图片绑定</button>
    </form>
</div>

<div class="container-fluid">
    <!-- 左边区域 - 显示上传的图片 -->
    <div id="uploadedImages" class="sidebar">
        <h2 class="mb-3">已上传的图片</h2>
        <ul id="uploadedImagesList" class="list-unstyled flex-grow-1"></ul>
    </div>

    <!-- 右边区域 - 显示分类后的文件夹和图片 -->
    <div id="classifiedImages" class="main-content">
        <h2 class="mb-3">分类后的文件夹和图片</h2>
        <div class="path-display" id="currentPath">全部文件</div>
        <ul id="classifiedImagesList" class="list-unstyled flex-grow-1">
            <li class="folder" onclick="loadFolderContent('')">根目录</li>
        </ul>
    </div>
</div>

<!-- 底部消息区 -->
<div class="message-box-container">
    <pre id="messageBox"></pre>
</div>

<!-- 自定义右键菜单 -->
<div id="contextMenu" class="context-menu" style="display: none;">
    <ul>
        <li onclick="deleteItem(event)">删除</li>
    </ul>
</div>

<script>
    let currentPath = "全部文件";
    let selectedEntry = null; // 用于保存当前选中的 entry 对象
    let selectedType = null; // 用于保存当前选中的 type 值

    async function uploadFiles() {
        if (document.getElementById("fileInput").files.length === 0) {
            logMessage('请选择文件');
            return;
        }

        const formData = new FormData(document.getElementById('uploadForm'));

        try {
            showLoadingIndicator(true);

            const response = await axios.post('/api/classifyImage/uploads', formData, {
                headers: {'Content-Type': 'multipart/form-data'}
            });
            logMessage('上传成功');
            document.getElementById('uploadForm').reset();
            loadUploadedImages();
        } catch (error) {
            logMessage(`上传失败: ${error.message}`);
        } finally {
            showLoadingIndicator(false);
        }
    }

    async function loadUploadedImages() {
        try {
            const response = await axios.post('/api/classifyImage/list', new URLSearchParams({type: '0'}), {
                headers: {'Content-Type': 'application/x-www-form-urlencoded'}
            });
            const responseData = response.data;
            if (responseData.code != 0) {
                throw new Error(responseData.msg || "未知错误");
            }
            const data = responseData.data || [];
            const ul = document.getElementById('uploadedImagesList');
            ul.innerHTML = ''; // 清空当前显示内容

            if (data.length === 0) {
                ul.innerHTML = '<li>暂无已上传图片</li>';
            } else {
                data.forEach(entry => {
                    if (!entry.isDir) {
                        createFileItem(ul, entry, '0');
                    }
                });
            }
        } catch (error) {
            logMessage(`获取已上传图片列表失败: ${error.message}`);
        }
    }

    async function loadFolderContent(path) {
        try {
            const response = await axios.post('/api/classifyImage/list', new URLSearchParams({type: '1', path: path}), {
                headers: {
                    'Content-Type': 'application/x-www-form-urlencoded' // 使用表单编码格式
                }
            });
            const responseData = response.data;
            if (responseData.code != 0) {
                throw new Error(responseData.msg || "未知错误");
            }
            const data = responseData.data || [];
            const ul = document.getElementById('classifiedImagesList');
            ul.innerHTML = ''; // 清空当前显示内容

            if (data.length === 0) {
                ul.innerHTML = '<li>该文件夹为空</li>';
            } else {
                data.forEach(entry => createFileItem(ul, entry, '1'));
            }
            updateCurrentPath(path);
        } catch (error) {
            logMessage(`获取文件列表失败: ${error.message}`);
        }
    }

    function createFileItem(parentUl, entry, type) {
        const li = document.createElement('li');
        li.className = 'file-item';

        // 创建图标元素
        const img = document.createElement('img');
        img.className = entry.isDir ? 'folder-icon' : 'file-icon';

        if (entry.isDir) {
            img.src = '/img/folder.png'; // 文件夹图标路径
            li.onclick = () => loadFolderContent(entry.relativePath);
        } else {
            img.src = isImage(entry) ? entry.url : '/img/file.png';
        }

        // 创建文本元素
        const span = document.createElement('span');
        span.className = 'file-name';
        span.textContent = entry.fileName;

        // 添加子元素到li
        li.appendChild(img);
        li.appendChild(span);

        // 绑定右键菜单事件
        li.addEventListener('contextmenu', function(event) {
            event.preventDefault(); // 阻止默认的右键菜单
            showContextMenu(event, entry, type); // 显示右键菜单并传递 entry 和 type
        });

        parentUl.appendChild(li);
    }

    function isImage(entry) {
        if (entry.mimeType) {
            return entry.mimeType.startsWith('image/');
        }
        return false;
    }

    async function classifyImages() {
        try {
            showLoadingIndicator(true);

            const response = await axios.post('/api/classifyImage/classify', {selectedImages: []}, {
                headers: {'Content-Type': 'application/json'}
            });
            const responseData = response.data;
            if (responseData.code != 0) {
                throw new Error(responseData.msg || "未知错误");
            }
            logMessage(response.data.msg || '分类成功');
            await Promise.all([loadUploadedImages(), loadFolderContent('')]);
        } catch (error) {
            logMessage(`分类失败: ${error.message}`);
        } finally {
            showLoadingIndicator(false);
        }
    }

    async function bindImages() {
        try {
            showLoadingIndicator(true);

            const response = await axios.post('/api/classifyImage/bind');

            if (response.data.code != 0) {
                throw new Error(response.data.msg || "未知错误");
            }

            logMessage(`绑定图片成功`);

            loadFolderContent('')
        } catch (error) {
            logMessage(`绑定图片失败: ${error.message}`);
        } finally {
            showLoadingIndicator(false);
        }
    }

    function logMessage(message) {
        const messageBox = document.getElementById('messageBox');
        const timestamp = new Date().toLocaleTimeString();
        messageBox.innerHTML += `[${timestamp}] ${message}\n`;
        messageBox.scrollTop = messageBox.scrollHeight; // 滚动到底部
    }

    function updateCurrentPath(path) {
        const pathDisplay = document.getElementById('currentPath');
        const parts = path.split('/').filter(part => part !== '');

        // 构建面包屑导航
        let breadcrumb = parts.length > 0 ? parts.map((part, index) => {
            if (index < parts.length - 1) { // 如果不是最后一个部分，则生成链接
                return `<a href="javascript:void(0)" onclick="loadFolderContent('${parts.slice(0, index + 1).join('/')}')">${part}</a>`;
            } else { // 最后一个部分不生成链接
                return part;
            }
        }).join(' > ') : "";

        // 添加“返回上级”链接（如果存在上级）
        let backLink = '';
        if (parts.length > 0) {
            backLink = `<a href="javascript:void(0)" onclick="loadFolderContent('${parts.slice(0, -1).join('/')}')">返回上级</a> | `;
        }

        // 确保“全部文件”在非根目录时可点击，并且不在根目录时出现在面包屑中
        let homeLink = parts.length > 0 ? `<a href="javascript:void(0)" onclick="loadFolderContent('')">全部文件</a>` : "全部文件";

        // 只有在非根目录时才将“全部文件”加入到路径显示中
        currentPath = parts.length > 0 ? `${backLink}${homeLink} > ${breadcrumb}` : homeLink;

        pathDisplay.innerHTML = currentPath;
    }

    function showLoadingIndicator(show) {
        if (show) {
            document.body.classList.add('loading');
        } else {
            document.body.classList.remove('loading');
        }
    }

    // 页面加载时初始化
    window.onload = async () => {
        await Promise.all([loadUploadedImages(), loadFolderContent('')]);
    };

    function showContextMenu(event, entry, type) {
        selectedEntry = entry; // 保存当前选中的 entry
        selectedType = type; // 保存当前选中的 type

        const contextMenu = document.getElementById('contextMenu');
        contextMenu.style.display = 'block';
        contextMenu.style.left = `${event.pageX}px`;
        contextMenu.style.top = `${event.pageY}px`;
    }

    document.addEventListener('click', function(event) {
        const contextMenu = document.getElementById('contextMenu');
        if (contextMenu.style.display === 'block' && event.button !== 2) {
            contextMenu.style.display = 'none';
        }
    });

    async function deleteItem(event) {
        if (selectedEntry && selectedType !== null) {
            try {
                showLoadingIndicator(true);

                let path = selectedEntry.relativePath;
                if (selectedEntry.url)
                    path = selectedEntry.relativePath + '/' + selectedEntry.fileName;
                const response = await axios.post('/api/classifyImage/remove', new URLSearchParams({type: selectedType, path: path}), {
                    headers: {
                        'Content-Type': 'application/x-www-form-urlencoded' // 使用表单编码格式
                    }
                });

                if (response.data.code != 0) {
                    throw new Error(response.data.msg || "未知错误");
                }

                logMessage(`删除成功: ${selectedEntry.fileName}`);

                if (selectedType == '1')
                    await loadFolderContent(extractFullPath());
                else
                    await loadUploadedImages();
            } catch (error) {
                logMessage(`删除失败: ${error.message}`);
            } finally {
                showLoadingIndicator(false);
            }
        }
    }

    function extractFullPath() {
        const currentPathDiv = document.getElementById('currentPath');
        const childNodes = currentPathDiv.childNodes; // 获取所有子节点
        let fullPath = '';
        let linkCount = 0; // 用于统计 <a> 标签的数量

        // 遍历所有子节点
        childNodes.forEach(node => {
            linkCount++;
            if (linkCount > 3) { // 跳过前两个 <a> 标签
                const originText = node.textContent.trim();
                if (originText) {
                    const text = originText.replace(/\||&gt;|>|\s/g, '');
                    if(text)
                        fullPath += text + '/';
                }
            }
        });

        // 去掉末尾多余的 / 和其他无效字符
        if (fullPath.endsWith('/')) {
            fullPath = fullPath.slice(0, -1);
        }

        return fullPath;
    }
</script>
</body>
</html>
